package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishDto;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

// 菜品控制器,完成菜品的增删改查
@RestController
@RequestMapping("/dish")
@Slf4j
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping
    public R<String> save(@RequestBody DishDto dishDto){
        log.info("[菜品新增 distDto:{}]",dishDto);
        // 调用业务方法，完成保存
        dishService.saveWithFlavor(dishDto);
        // 保存的时候，清空当前分类的菜品
        String key = "dish_"+dishDto.getCategoryId()+"_"+dishDto.getStatus();
        redisTemplate.delete(key);
        return R.success("保存菜品成功");
    }

    @GetMapping("/page")
    public R<Page> page(Integer page, Integer pageSize, String name){
        log.info("[菜品的分页查询  page:{},pageSize:{},name:{}]",page,pageSize,name);

        // 查询，还是以DishService查询为主，先把原生的菜品分页数据拿到
        //  select * from dish;
        // 1. 构建分页查询对象 - 目的还是以Dish(菜品表）为主进行查询
        Page<Dish> dishPage = new Page<Dish>(page,pageSize);
        // 2. 加条件查询
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(name!=null,Dish::getName,name);
        queryWrapper.orderByDesc(Dish::getUpdateTime);
        // 3.获取到原生的分页数据
        dishService.page(dishPage,queryWrapper);
        //Page<DishDto> pageDishDto = new Page<>();
        // 以下是非lambda的写法
        // 查询完之后，这个是dispPage里面的是否有了分页的数据和总条数
        // 此时的records存储是Dish对象，没有分类的名称，是不能直接给前端，如果给了，是没有分类名称
        /*
        List<Dish> records = dishPage.getRecords();
        long total = dishPage.getTotal();
        // 此时比较传统的做法是：把Dish->DishDto 复制
        List<DishDto> newRecords = new ArrayList<>();
        for (Dish dish:records){
            // 把每条记录，复制为DishDto
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish,dishDto);
            // 当前菜品是有分类的ID，我们只需要去分类的serivice去查询一下就可以了
            // 少了一个分类名称的查询,根据当前菜品的分类，去查询一下分类的名称即可。
            Category category = categoryService.getById(dish.getCategoryId());
            dishDto.setCategoryName(category.getName());

            newRecords.add(dishDto);
        }
        // 返回的结果一定是DishDto，因为里面有分类的名称
        pageDishDto.setRecords(newRecords);
        pageDishDto.setTotal(total);
        */

        // 以下是lambda写法
        Page<DishDto> pageDishDto = new Page<>();
        // dishPage<Dish>
        // 把数据封装到DishDto中,第3个参数，先忽略records，因为后续需要修改里面的数据
        // records<Dish>,这个时候不需要复制，复制过程，可以忽略掉不需要的属性
        // 这个时候，把dishPage 复制为pageDishDto的时候，仅把总记录时给复制过去
        BeanUtils.copyProperties(dishPage,pageDishDto,"records");
        //4). 遍历分页查询列表数据, 把Dish对象转为DishDto对象，同时赋值分类名称
        List<Dish> recordsDish = dishPage.getRecords();
        List<DishDto>   recordsDishDto = recordsDish.stream().map((item)->{
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);
            //item.getCategoryId()
            Category category = categoryService.getById(item.getCategoryId());
            if(category != null){
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }
            return dishDto;
        }).collect(Collectors.toList()); // 把返回的对象，转换为一个集合对象
        pageDishDto.setRecords(recordsDishDto);
        return R.success(pageDishDto);
    }

    // 根据菜品ID，获取菜品信息
    @GetMapping("/{id}")
    public R<DishDto> findById(@PathVariable Long id){
        log.info("[根据ID获取菜品  id:{}]",id);
        // 调用DishService的一个方法，根据ID获取菜品，但是一定要带着菜品口味
        DishDto dishDto =  dishService.getByIdWithFlavor(id);
        return R.success(dishDto);
    }

    @PutMapping
    public R<String> update(@RequestBody DishDto dishDto){
        log.info("[更新菜品 distDto:{}]",dishDto);
        // 调用service完成更新业务
        dishService.updateWithFlavor(dishDto);
        String key ="dish_*";
        // 找到所有dish_开头的key
        Set keys = redisTemplate.keys(key);
        // 批量的删除
        redisTemplate.delete(keys);
        return R.success("更新成功");
    }

    @Autowired
    private DishFlavorService dishFlavorService;

    // 给移动端提供列表
    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish){
        List<DishDto> redisDishDtoList = null;
        // 尝试从Redis中拿列表
        String key = "dish_"+dish.getCategoryId()+"_"+dish.getStatus();
        redisDishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);
        if(redisDishDtoList != null){
            log.info("[从redis，读取分类下的菜品 key:{}]",key);
            return R.success(redisDishDtoList);
        }

        //构造查询条件
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(dish.getCategoryId() != null ,Dish::getCategoryId,dish.getCategoryId());
        //添加条件，查询状态为1（在售状态）的菜品
        queryWrapper.eq(Dish::getStatus,1);
        //添加排序条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

        List<Dish> list = dishService.list(queryWrapper);

        List<DishDto> dishDtoList = list.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if(category != null){
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }

            //当前菜品的id
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
            //SQL:select * from dish_flavor where dish_id = ?
            List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
            dishDto.setFlavors(dishFlavorList);

            return dishDto;
        }).collect(Collectors.toList());
        // 把从数据库获取的列表，存入redis
        redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);

        return R.success(dishDtoList);
    }

}
